<template>
  <div class="digital-overlay">
    <div class="digital-modal">
      <div class="digital-modal-header">
        <div class="title" >数智人配音文本</div>
        <div class="icon" @click="onClose">
          <i class="iconfont icon-close"></i>
        </div>
      </div>
      <div class="digital-modal-body">
        <div class="container">
          <!-- 工具栏 -->
          <div class="words-tools">
            <div class="tool-common">
              <div class="tool-item" @click.stop="onBreakInsert">
                <i class="iconfont icon-speak-break icon"></i>
                <span>插入停顿</span>
              </div>
              <div class="tool-item" @click.stop="onOpenPickMusicPanel">
                <!-- <i class="iconfont icon-speak-break icon"></i>
                <span>选音色</span> -->
                <template v-if="pickMusic?.title">
                  <div class="pick-img-container">
                    <img class="pick-img" :src="pickMusic.imgUri" />
                  </div>
                  <span>音色: {{ pickMusic.title }}</span>
                  <MusicEdit 
                    v-if="isOpenPickMusicPanel"
                    :pickMusic="pickMusic"
                    :pickMusicList="pickMusicList"
                    :musicConfig="musicConfig"
                    @select-pickMusic="selectPickMusic"
                  />
                </template>
              </div>
              <div class="tool-item"
                  :class="{
                    on: enableCheck,
                  }"
                  @click.stop="onEnableCheck"
              >
                <i class="iconfont icon-speak-check icon"></i>
                <span>读音检测: {{ enableCheck ? '开' : '关' }}</span>
              </div>
            </div>
            <!-- <div class="tool-player">
              <button class="play-btn">
                <img src="../assets/play.png">
                <span data-v-a0d89cbf="">试听</span>
              </button>
            </div> -->
          </div>
          <!-- 富文本 -->
          <div id="words-container" @click="onFocus">
            <template v-if="ssmlRenderer?.total">
              <RenderNode
                v-for="(child, i) in ssmlRenderer?.children"
                :ssmlRenderer="ssmlRenderer"
                :key="child?.id"
                :index="i"
                :checked="child?.checked"
                :type="child?.type"
                :data-type="child?.dataType"
                :data="child?.data"
                :attribs="child?.attribs"
                :mark="child?.mark"
                :marked="child?.marked"
                :default-mark="child?.defaultMark"
                :enable-check="enableCheck"
                @mark-click="(event: any) => onMarksShow(event, child)"
                @word-click="onWordClick"
              />
            </template>
          </div>
          <div class="input-count">{{ ssmlRenderer.length }} / {{ maxSSMLTextLength }}</div>
        </div>
        <div
          v-if="showPannel"
          class="select-pannel"
          :class="{
            marked: pannelNode?.marked,
            break: pannelNode?.dataType === 'break',
          }"
          :style="{
            top: `${pannelTop + 30 + 76}px`,
            left: `${pannelLeft + 30}px`,
          }"
          @click.stop=""
        >
          <div
            v-for="option in pannelOptions"
            :key="option.result"
            class="select-option"
            @click.stop="onMark(option)"
          >
            <span>{{ option.isZh ? option.result : option.label }}</span>
          </div>
          <div
            :key="removeMarkItem.result"
            class="select-option"
            @click.stop="onMark(removeMarkItem)"
          >
            <span>
              {{
                pannelNode?.dataType === 'break'
                  ? '移除停顿'
                  : removeMarkItem.label
              }}
            </span>
          </div>
        </div>
      </div>
      <div class="digital-modal-footer">
        <div class="info">
          <div class="info-item">
            <span class="tips">未修订多音字标记为橙色标记：</span>
            <span class="rect orange"></span>
          </div>
          <div class="info-item">
            <span class="tips">已修订多音字标记为青色标记：</span>
            <span class="rect blue"></span>
          </div>
        </div>
        <button class="digital-button" @click="onSave()">保存</button>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { Options, Vue } from 'vue-class-component';
import { SSMLEngine, SSMLRenderer } from '../utils/ssml'
import RenderNode from './RenderNode.vue'
import MusicEdit from './MusicEdit.vue'
import type { SSMLRenderNode, SelectItem } from '../utils/ssml/type';
import { Voice, MusicConfig } from '../utils/common/voice'
import { SSMLProvider } from '../utils/ssml/type';
import { floatReg } from '../utils/regexp';
import nzh from '../utils/nzh';
import arab2cn from '../utils/common/arab2cn'
import { copy } from '../utils/common/copy';
// import { languageCheck } from '../utils/language-check';

const ONSAVE = 'onSave';

@Options({
  props: {
    ssml: ''
  },
  emits:[ONSAVE],//数据吐给窗体的调用者
  components: {
    RenderNode,
    MusicEdit
  },
  data() {
    const inputEl = document.createElement('input');
    inputEl.className = 'zego-insert-cursor';

    const emptyInput = document.createElement('textarea');
    emptyInput.placeholder = '在此请输入台词文本，点击合成，即可生成视频';
    emptyInput.className = 'zego-empty-input';

    let pannelOptions: Array<SelectItem> = [];
    let pannelNode: SSMLRenderNode = {} as SSMLRenderNode;
    let nextEl: any = null;
    let checkTimer: number | null = null;
    const removeMarkItem = {
      origin: '',
      result: 'default',
      mark: '',
      label: '取消标记',
      isZh: false,
    };
    const pickMusicList: Array<Voice> = window.voiceList; // 音色
    let pickMusic: Voice = pickMusicList[0]
    let musicConfig: MusicConfig =  {
        speechRate: 10,
        pitchRate: 0,
        volume: 50,
    };
    return {
      maxSSMLTextLength: 1800,
      minSSMLTextLength: 5,
      enableCheck: true,
      ssmlEngine: new SSMLEngine(),
      ssmlRenderer: new SSMLRenderer(),
      con: null, // container
      inputEl, // 输入光标
      emptyInput, // 空白节点
      showPannel: false, // 字典下拉选择
      pannelOptions, // 点击标记，下拉选项
      pannelNode, //标记的节点
      pannelTop: 0,
      pannelLeft: 0,
      removeMarkItem,
      nextEl,
      checkTimer,
      pickMusicList,
      pickMusic,
      musicConfig, // 语速
      isOpenPickMusicPanel: false,
    };
  },
  async mounted() {
    this.ssmlEngine.setVDomBySSML(this.ssml);
    this.ssmlRenderer.loadModel(this.ssmlEngine.getRenderer());
    // console.log(this.ssmlRenderer.children)
    this.bindGlobalEvent();
    const container = this.getContainer();
    if (!this.ssmlRenderer.total) {
      if (container) {
        container.appendChild(this.emptyInput);
        this.emptyInput.focus();
      }
    }
    if (this.enableCheck) {
      if (this.ssmlRenderer.total !== 0) {
        this.ssmlRenderer.checkMerge()
        this.ssmlRenderer.cursor = this.ssmlRenderer.total;
        this.nextEl = null;
        await this.insertBeforeNextEl();
      }
    }
  },
  methods: {
    onClose() {
      // NOTE 元分身对应custom_ssml，阿里云对应ssml 转语音要区分厂商
      const ssml = this.ssmlEngine.setVDomByRenderer(this.ssmlRenderer).getSSML();
      const custom_ssml = this.ssmlEngine.getSSML(SSMLProvider.YUAN);

      this.$emit(ONSAVE, { 
        ssml, 
        custom_ssml, 
        musicConfig:this.musicConfig,
        pickMusic: this.pickMusic
      });
    },
    onSave() {
      if (this.ssmlRenderer.length > this.maxSSMLTextLength) {
        alert(`最多只能输入${this.maxSSMLTextLength}字`);
        return;
      }
      if (this.ssmlRenderer.length < this.minSSMLTextLength) {
        alert('请输入至少5个有效文字');
        return;
      }
      if (this.checkTimer) {
        clearTimeout(this.checkTimer);
        this.checkTimer = null;
      }

      // TODO 音色数据检验
      // const { fatal, supportLangCnames, unSupportLangCnames } = languageCheck(this.ssmlRenderer.getText(0, this.ssmlRenderer.total), this.pickMusic.languageList)
      // if (fatal) {
      //   console.error(`包含不支持的语言：${unSupportLangCnames.join('、')}`);
      //   alert(`当前音色仅支持输入${supportLangCnames.join('、')}，请切换音色后操作`);
      //   return
      // } else {
      //   if (unSupportLangCnames.length) {
      //     console.warn(`包含不支持的语言：${unSupportLangCnames.join('、')}`);
      //     const yes = confirm(`检测到当前输入内容为可能与音色支持的语种不匹配，建议试听后进行保存`);
      //     if (!yes) return
      //   }
      // }
      // console.log('language check passed');

      this.onClose();
      this.unbindGlobalEvent();
    },
    inputCheck() {
      if (this.ssmlRenderer.total) {
        this.emptyInput.value = '';
        this.emptyInput.remove();
      } else {
        this.inputEl.value = '';
        this.inputEl.remove();
        const container = this.getContainer()
        if (container) {
          container.appendChild(this.emptyInput);
          this.emptyInput.focus();
        }
      }
    },
    getContainer() {
      if (!this.con) {
        this.con = document.getElementById('words-container') as HTMLElement;
      }
      return this.con;
    },
    async onKeydown(e: KeyboardEvent) { // 处理单个快捷键
      console.log('[onKeydown]', e);
      if (e.isComposing) return;
      if (!this.ssmlRenderer.total) return;
      switch (e.code) {
        case 'PageUp':
        case 'Home': {
          this.ssmlRenderer.cursor = 0;
          this.inputEl.remove();
          this.nextEl = this.getContainer().firstElementChild;
          await this.insertBeforeNextEl();
          break;
        }
        case 'PageDown':
        case 'End': {
          this.ssmlRenderer.cursor = this.ssmlRenderer.total;
          this.inputEl.remove();
          this.nextEl = null;
          await this.insertBeforeNextEl();
          break;
        }
        case 'Backspace': {
          if (this.isSelected()) return;

          if (this.ssmlRenderer.cursor <= 0) return;
          this.ssmlRenderer.removeChilds(this.ssmlRenderer.cursor - 1, this.ssmlRenderer.cursor);
          this.ssmlRenderer.cursor--;
          if (!this.ssmlRenderer.total) this.nextEl = null;
          this.inputCheck();
          break;
        }
        case 'Delete': {
          if (this.isSelected()) return;

          if (this.ssmlRenderer.cursor >= this.ssmlRenderer.total) return;
          this.nextEl = this.getValidNextSibling(this.nextEl?.nextElementSibling);
          this.ssmlRenderer.removeChilds(this.ssmlRenderer.cursor, this.ssmlRenderer.cursor + 1);
          this.inputCheck();
          break;
        }
        case 'ArrowRight': {
          if (this.ssmlRenderer.cursor >= this.ssmlRenderer.total) return;
          this.ssmlRenderer.cursor++;
          this.nextEl = this.getValidNextSibling(this.nextEl?.nextElementSibling);
          await this.insertBeforeNextEl();
          break;
        }
        case 'ArrowLeft': {
          if (this.ssmlRenderer.cursor <= 0) return;
          this.ssmlRenderer.cursor--;
          this.nextEl = this.getValidPreviousSibling(this.inputEl.previousElementSibling);
          await this.insertBeforeNextEl();
          break;
        }
        case 'NumpadEnter':
        case 'Enter': {
          if (this.ssmlRenderer.cursor <= 0) return;
          if (this.ssmlRenderer.length >= this.maxSSMLTextLength) return;
          this.ssmlRenderer.insertLineBreak(this.ssmlRenderer.cursor);
          await this.insertBeforeNextEl();
          if (this.enableCheck) {
            if (this.checkTimer) {
              clearTimeout(this.checkTimer);
            }
            this.checkTimer = setTimeout(() => {
              this.check();
            }, 5000);
          }
          break;
        }
        default:
      }
    },
    async onEdit(e: InputEvent | Record<string, any>) { // 处理输入
      if (e.inputType === 'deleteContentForward') return;
      if (e.inputType === 'deleteContentBackward') return;
      if (e.isComposing) return;
      let data: string =
        e.inputType === 'insertFromPaste' ? e.target.value : e.data;
      e.target.value = '';
      
      // store.textDriverAllPaused(store.currentSceneIndex)
      if (!data) return;
      // data = proxy.$filtrValue(data)
      if (this.ssmlRenderer.length + data.length > this.maxSSMLTextLength) {
        alert(`最多只能输入${this.maxSSMLTextLength}字`);
        data = data.slice(0, this.maxSSMLTextLength - this.ssmlRenderer.length);
      }
      if (data.length) {
        this.ssmlRenderer.insertChilds(data, this.ssmlRenderer.cursor);
        await this.insertBeforeNextEl();
        if (this.enableCheck) {
          if (this.checkTimer) {
            clearTimeout(this.checkTimer);
          }
          this.checkTimer = setTimeout(() => {
            this.check();
          }, 5000);
        }
      }
    },
    async onProcess(e: KeyboardEvent) { // 处理组合快捷键
      const { ctrlKey, metaKey, altKey, shiftKey, code } = e
      const removeSelection = async (selection: any) => {
        const { nextNode, startIndex, endIndex } = selection;
        console.log('remove', startIndex, endIndex + 1);
        if (startIndex > -1 && endIndex > -1) {
          this.ssmlRenderer.removeChilds(startIndex, endIndex + 1);
          this.ssmlRenderer.cursor = startIndex;
          this.nextEl = nextNode;
          if (this.ssmlRenderer.total) {
            await this.insertBeforeNextEl();
          }
        }
      };

      if ((ctrlKey || metaKey) && shiftKey) {
        switch (code) {
          case 'KeyZ': {
            e.preventDefault();
            this.inputEl.remove();
            this.ssmlRenderer.forwordHistory();
            return;
          }
        }
      } else if (ctrlKey || metaKey) {
        switch (code) {
          case 'KeyA': {
            e.preventDefault();
            this.inputEl.remove();
            document.getSelection()?.selectAllChildren(this.getContainer());
            return;
          }
          case 'KeyC': {
            const selection = this.getSelectionInfo();
            const { text, startIndex, endIndex } = selection;
            if (!text) return;
            e.preventDefault();
            await copy(this.ssmlRenderer.getText(startIndex, endIndex + 1, { break: '' }));
            return;
          }
          case 'KeyV': {
            if (this.isSelected()) {
              const selection = this.getSelectionInfo();
              removeSelection(selection);
            }
            break;
          }
          case 'KeyX': {
            if (!this.isSelected()) return;
            const selection = this.getSelectionInfo();
            const { startIndex, endIndex } = selection;
            e.preventDefault();
            await copy(this.ssmlRenderer.getText(startIndex, endIndex + 1, { break: '' }));
            removeSelection(selection);
            break;
          }
          case 'KeyY': {
            e.preventDefault();
            this.ssmlRenderer.forwordHistory();
            await this.$nextTick();
            this.nextEl = this.getContainerValidChildren()[this.ssmlRenderer.cursor + 1] || null;
            this.insertBeforeNextEl();
            return;
          }
          case 'KeyZ': {
            e.preventDefault();
            this.ssmlRenderer.backHistory();
            await this.$nextTick();
            this.nextEl = this.getContainerValidChildren()[this.ssmlRenderer.cursor + 1] || null;
            if (this.ssmlRenderer.total !== 0) await this.insertBeforeNextEl();
            return;
          }
          default:
        }
      } else {
        if (altKey) return
        if (!this.isSelected()) return;
        switch (code) {
          case 'Backspace':
          case 'Delete': {
            e.preventDefault();
            const selection = this.getSelectionInfo();
            console.log('getSelectionInfo ===>', selection)
            removeSelection(selection);
            break;
          }
          default: {
            if (
              code &&
              !/^(F[0-9]{1,2}$)|(Tab)$|(NumLock)$|(Control)|(Pause$)|(Commond)|(Shift)|(Alt)|(Control)|(Meta)|(ContextMenu)|(Page)|(Home)|(End)|(CapsLock)|(Ins)|(ScrollLock)|(Pause)|(Escape)|(Arrow)/.test(
                code
              )
            ) {
              const selection = this.getSelectionInfo();
              removeSelection(selection);
            }
          }
        }
      }
    },
    bindGlobalEvent() {
      this.inputEl.addEventListener('keydown', this.onKeydown);
      this.inputEl.addEventListener('input', this.onEdit);
      this.inputEl.addEventListener('compositionend', this.onEdit);

      this.emptyInput.addEventListener('input', this.onEdit);
      this.emptyInput.addEventListener('compositionend', this.onEdit);
      document.documentElement.addEventListener('keydown', this.onProcess);       
      document.documentElement.addEventListener('click', this.onClosePickMusicPanel)
    },
    unbindGlobalEvent() {
      this.inputEl.removeEventListener('keydown', this.onKeydown);
      this.inputEl.removeEventListener('input', this.onEdit);
      this.inputEl.removeEventListener('compositionend', this.onEdit);

      this.emptyInput.removeEventListener('input', this.onEdit);
      this.emptyInput.removeEventListener('compositionend', this.onEdit);
      document.documentElement.removeEventListener('keydown', this.onProcess);
      document.documentElement.removeEventListener('click', this.onClosePickMusicPanel)
    },
    async onMarksShow(event: MouseEvent, node: SSMLRenderNode) {
      
      switch (node.dataType) {
        case 'word': {
          this.pannelOptions = [
            {
              origin: node.data!,
              result: 'id',
              mark: '字母',
              label: `字母：${String.prototype.toLocaleUpperCase.call(node.data!)}`,
              isZh: false,
            },
          ];
          break;
        }
        case 'number': {
          const data = node.data!
          const isFloat = floatReg.test(data)
          const tooLong = data.split('.')[0].length > 16
          const valueSay = nzh.encodeS(data)
          const telSay = isFloat ? '' : arab2cn(data, { tel: true })
          const numSay = arab2cn(data)
          const says: Array<SelectItem> = []

          const currencySay = {
            origin: data,
            result: 'currency',
            mark: '数值',
            label: `数值：${tooLong ? '暂不支持预览' : valueSay}`,
            isZh: false,
          }
          if (!tooLong) {
            says.push(currencySay)
          }
          const telephoneSay = {
            origin: data,
            result: 'telephone',
            mark: '电话',
            label: `电话：${telSay}`,
            isZh: false,
          }
          if (!isFloat) {
            says.push(telephoneSay)
          }
          const digitsSay = {
            origin: data,
            result: 'digits',
            mark: '数字',
            label: `数字：${numSay}`,
            isZh: false,
          }
          says.push(digitsSay)
          this.pannelOptions = says
          break;
        }
        case 'chinese': {
          this.pannelOptions = this.ssmlRenderer.multiPYDict[node.data!];
          if (this.pannelOptions.length === 1) return
          break;
        }
        case 'break': {
          this.pannelOptions = [
            {
              origin: ' ',
              result: '500ms',
              mark: '短',
              label: '短',
              isZh: false,
            },
            {
              origin: ' ',
              result: '1s',
              mark: '中',
              label: '中',
              isZh: false,
            },
            {
              origin: ' ',
              result: '2s',
              mark: '长',
              label: '长',
              isZh: false,
            },
          ];
          break;
        }
        default:
      }
      // console.log('[onMarksShow]', event, node, this.pannelOptions);
      const target = (event.currentTarget as any).parentNode as HTMLElement;
      const container = this.getContainer();
      const { offsetTop, offsetLeft, clientWidth, clientHeight } = target;
      const { scrollTop } = container;
      this.showPannel = true;
      this.pannelNode = node;
      document.documentElement.addEventListener('click', this.exitPannel);
      container.addEventListener('scroll', this.exitPannel);
      await this.$nextTick();
      this.pannelTop = offsetTop + clientHeight - scrollTop;
      this.pannelLeft = offsetLeft + clientWidth / 2;
    },
    async onWordClick ({ target, event, index }: { target: HTMLElement, event: MouseEvent, index: number }){
      // console.log('[onWordClick]', target, event, index);
      if (this.isSelected()) {
        return;
      }
      let offset = 0
        if (target) {
          this.nextEl = target
        } else {
          if (!event) return
          const target = event.currentTarget as HTMLElement;
          const rect = target.getBoundingClientRect();
          const x = event.clientX - rect.left;
          const isClickRight = rect.width / 2 < x;
          this.inputEl.remove();
          // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
          this.nextEl = isClickRight ? this.getValidNextSibling(target.nextElementSibling)! : target;
          offset = isClickRight ? 1 : 0;
        }
        this.ssmlRenderer.cursor = index + offset;
        await this.insertBeforeNextEl();
    },
    exitPannel() {
      this.showPannel = false;
      this.pannelNode = void 0;
      document.documentElement.removeEventListener('click', this.exitPannel);
      this.getContainer().removeEventListener('scroll', this.exitPannel);
    },
    async onMark(selected: SelectItem) {
      if (!this.pannelNode) return;
      const prevMark = this.pannelNode.mark;
      if (this.removeMarkItem === selected) {
        if (this.pannelNode.dataType === 'break') {
          const pannelNodeIndex = this.ssmlRenderer.children
            .findIndex((child:SSMLRenderNode) => child === this.pannelNode)
          this.ssmlRenderer.removeChilds(pannelNodeIndex, pannelNodeIndex + 1);
        }
        this.pannelNode.attribs = {};
        this.pannelNode.mark = '';
        this.pannelNode.marked = false;
      } else {
        switch (this.pannelNode.dataType) {
          case 'word':
          case 'number': {
            if (selected) {
              this.pannelNode.attribs['interpret-as'] = selected.result;
              this.pannelNode.mark = selected.mark;
              this.pannelNode.marked = true;
            }
            break;
          }
          case 'chinese': {
            if (selected) {
              this.pannelNode.attribs = {
                alphabet: 'py',
                ph: selected.pinyin,
              };
              this.pannelNode.mark = selected.result;
              this.pannelNode.marked = true;
            }
            break;
          }
          case 'break': {
            if (selected) {
              this.pannelNode.attribs = {
                time: selected.result,
              };
              this.pannelNode.mark = selected.mark;
              this.pannelNode.marked = true;
            }
            break;
          }
          default:
        }
      }
      if (prevMark !== this.pannelNode.mark) {
        // store.textDriverAllPaused(store.currentSceneIndex)
      }
      // console.warn('[onMark]', this.pannelNode, this.ssmlEngine.getSSML());
      
      this.exitPannel();
    },
    async insertBeforeNextEl() {
      const container = this.getContainer()
      await this.$nextTick();
      if (this.nextEl) {
        container && container.insertBefore(this.inputEl, this.nextEl);
      } else {
        container && container.appendChild(this.inputEl);
      }
      this.inputEl.focus();
    },
    async onFocus() {
      if (this.isSelected()) {
        return;
      }

      if (this.ssmlRenderer.total) {
        this.ssmlRenderer.cursor = this.ssmlRenderer.total;
        this.inputEl.remove();
        this.nextEl = this.getContainer().lastChild;
        await this.insertBeforeNextEl();
      }
    },
    isSelected() {
      return !!document.getSelection()?.toString().replace(/\r|\n/g, '')
    },
    getValidNextSibling(node: Element | null): Element | null {
      return node === this.inputEl || node?.className === 'lineBreak' ? this.getValidNextSibling(node?.nextElementSibling) : node
    },
    getValidPreviousSibling (node: Element | null): Element | null {
      return node === this.inputEl || node?.className === 'lineBreak' ? this.getValidNextSibling(node?.nextElementSibling) : node
    },
    getContainerValidChildren() {
      return Array.from(this.getContainer().children)
        .filter(child => this.isElementValid(child))
    },
    isElementValid(node: Element) {
      return node !== this.inputEl && node?.className !== 'lineBreak'
    },
    async check() {
      if (this.enableCheck) {
        if (this.ssmlRenderer.total !== 0) {
          this.ssmlRenderer.checkMerge();
          this.ssmlRenderer.cursor = this.ssmlRenderer.total;
          this.nextEl = null;
          await this.insertBeforeNextEl();
        }
      } else {
        if (this.checkTimer) {
          clearTimeout(this.checkTimer);
          this.checkTimer = null;
        }
      }
    },
    getSelectionInfo() {
      const selection = document.getSelection();
      const container = this.getContainer()
      let startNode: Node | null = null;
      let endNode: Node | null = null;
      let startIndex = -1;
      let endIndex = -1;
      let startOver = false;
      let endOver = false;
      const selectText = selection?.toString().replace(/\r|\n/g, '') || '';
      if (selection && selectText) {
        const anchorNode = selection.anchorNode as HTMLElement;
        const focusNode = selection.focusNode as HTMLElement;
        startNode = anchorNode;
        endNode = focusNode;
        if (anchorNode === container) {
          startOver = true;
        } else {
          if (
            anchorNode?.nodeType === 3 &&
            this.getParentElement(anchorNode, 3) === container
          ) {
            startNode = this.getParentElement(anchorNode, 2);
          } else if (anchorNode?.nodeType === 1) {
            if (this.getParentElement(anchorNode, 2) === container) {
              if (anchorNode.className === 'blank') {
                console.log('startNode ===> blank')
                startNode = this.getValidNextSibling(this.getParentElement(anchorNode)?.nextElementSibling || null);
              } else {
                console.log('startNode ===> anchorNode.parentElement')
                startNode = this.getParentElement(anchorNode);
              }
            } else if (this.getParentElement(anchorNode) === container) {
              console.log('startNode ===> anchorNode')
              startNode = anchorNode;
            }
            startIndex = this.getContainerValidChildren()
              .findIndex((node: Node) => node === startNode);
          }
          startIndex = this.getContainerValidChildren()
            .findIndex((node: Node) => node === startNode);
        }

        if (focusNode === container) {
          endOver = true;
        } else {
          if (focusNode?.nodeType === 3 && this.getParentElement(focusNode, 3) === container) {
            endNode = this.getParentElement(focusNode, 2);
          } else if (focusNode?.nodeType === 1) {
            if (this.getParentElement(focusNode, 2) === container) {
              if (focusNode.className === 'blank') {
                console.log('endNode ===> blank')
                endNode = this.getValidNextSibling(this.getParentElement(focusNode)?.nextElementSibling || null);
              } else {
                console.log('endNode ===> focusNode.parentElement')
                endNode = this.getParentElement(focusNode);
              }
            } else if (this.getParentElement(focusNode) === container) {
              console.log('endNode ===> focusNode')
              endNode = focusNode;
            }
            endIndex = this.getContainerValidChildren()
              .findIndex((node: Node) => node === endNode);
          }
          endIndex = this.getContainerValidChildren()
            .findIndex((node: Node) => node === endNode);
        }
        if (startIndex > -1 && endOver) {
          const {
            previousElementSibling,
            nextElementSibling,
          } = startNode as HTMLElement;
          if (
            previousElementSibling &&
            selection.containsNode(previousElementSibling)
          ) {
            endNode = container.firstElementChild;
            endIndex = 0;
          }
          if (nextElementSibling && selection.containsNode(nextElementSibling)) {
            endNode = container.lastElementChild;
            endIndex = this.ssmlRenderer.total;
          }
          console.log('AutoComplete EndIndex ===>', endIndex);
        }
        if (endIndex > -1 && startOver) {
          const {
            previousElementSibling,
            nextElementSibling,
          } = endNode as HTMLElement;
          if (previousElementSibling && selection.containsNode(previousElementSibling)) {
            startNode = container.firstElementChild;
            startIndex = 0;
          }
          if (nextElementSibling && selection.containsNode(nextElementSibling)) {
            startNode = container.lastElementChild;
            startIndex = this.ssmlRenderer.total;
          }
          console.log('AutoComplete StartIndex ===>', startIndex);
        }
        if (startOver && endOver) {
          console.log('Select All');
          startIndex = 0;
          startNode = container.firstElementChild;
          endNode = container.lastElementChild;
          endIndex = this.ssmlRenderer.total;
        }
        if (startIndex > endIndex) {
          [startNode, endNode] = [endNode, startNode];
          [startIndex, endIndex] = [endIndex, startIndex];
        }
        // 偏移一位检测修正，仅单字符节点做修正
        const ssmlText = this.ssmlRenderer.getText(startIndex, endIndex + 1)
        if (ssmlText.length === 1 && selectText[0] !== ssmlText[0]) {
          startNode = this.getValidNextSibling((startNode as HTMLElement).nextElementSibling)
          startIndex++
          console.log('start offset autofix ===>', startIndex)
        }
        if (ssmlText.length === 1 && selectText[selectText.length - 1] !== ssmlText[ssmlText.length - 1]) {
          endNode = this.getValidPreviousSibling((endNode as HTMLElement).previousElementSibling)
          endIndex--
          console.log('end offset autofix ===>', endIndex)
        }
      }
      const nextNode = this.getValidNextSibling((endNode as HTMLElement)?.nextElementSibling);
      console.log('nextNode ===>', nextNode)
      return {
        text: startIndex > -1 && endIndex > -1 ? selectText : '',
        startNode,
        endNode,
        startIndex,
        endIndex,
        nextNode,
      };
    },
    getParentElement(node: Element | null, level = 1): Element | null {
      const parentElement = node?.parentElement || null
      if (level > 1) return this.getParentElement(parentElement, level - 1)
      return parentElement
    },
    async onBreakInsert() {
      console.log('onBreakInsert');
      this.ssmlRenderer.insertBreak(this.ssmlRenderer.cursor);
      if (this.enableCheck) {
        if (this.checkTimer) {
          clearTimeout(this.checkTimer);
        }
        this.checkTimer = setTimeout(() => {
          this.check();
        }, 5000);
      }
      await this.insertBeforeNextEl();
    },
    onEnableCheck() {
      this.enableCheck = !this.enableCheck;
      // emit('toggleEnableCheck', !props.enableCheck);
      // store.textDriverAllPaused(store.currentSceneIndex)
    },
    selectPickMusic(pm: Voice) {
      this.pickMusic = pm;
    },
    onClosePickMusicPanel() {
      this.isOpenPickMusicPanel = false;
    },
    onOpenPickMusicPanel() {
      this.isOpenPickMusicPanel = true;
    },
  },
})
export default class ContentModal extends Vue { }
</script>

<style scoped>
.digital-modal-footer .info {
  display: flex;
}
.digital-modal-footer .tips {
    font-size: 12px;
    color: #999;
}
.digital-modal-footer .rect {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 2px;
}
.digital-modal-footer .orange {
  background: #fcb507;
}
.digital-modal-footer .blue {
  background: #60ccdc;
}
.digital-modal-header .icon {
  cursor: pointer;
  padding: 2px;
}
.info .info-item {
  margin: 0 10px;
}
.info .info-item:first-child {
  margin-left: 0px;
}
.digital-modal-body .container {
  height: 100%;
  width: 100%;
  display: flex;
  flex-direction: column;
  border: 1px solid #e6e6e6;
  border-radius: 8px;
  position: relative;
  overflow-y: hidden;
}
.digital-modal-body .words-tools {
  width: 100%;
  height: 76px;
  display: flex;
  align-items: center;
  background: #f8f8fc;
  border-bottom: 1px solid #e6e6e6;
  user-select: none;
  position: relative
}
.words-tools .tool-common {
  flex: 1;
  display: flex;
  align-items: center;
}
.words-tools .tool-common .tool-item {
  font-size: 12px;
  padding: 0 20px;
  height: auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  border-right: 1px solid #e6e6e6;
  width: 130px;
  overflow: hidden;
  color: #666666;
  cursor: pointer;
}
.words-tools .tool-common .tool-item:hover {
    color: #4d5ef9;
}
.words-tools .tool-common .tool-item .icon {
  font-size: 20px;
  font-family: "iconfont" !important;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
}
.words-tools .tool-common .tool-item.on {
  color: #4d5ef9;
}
#words-container {
  width: 100%;
  flex: 1;
  background: rgba(248, 248, 252, 0.5);
  padding: 10px 20px;
  overflow: hidden scroll;
}
.input-count {
  padding: 6px;
  background: rgba(248, 248, 252, 0.5);
  user-select: none;
  text-align: right;
}
#words-container::-webkit-scrollbar-thumb {
  background: #e7ecf9;
}
.select-pannel {
  position: absolute;
  z-index: 10;
  left: 0;
  top: 0;
  transform: translate(-50%);
  padding: 6px 12px;
  background: #ffffff;
  box-shadow: 0px 0px 7px 0px rgba(115, 115, 116, 0.3);
  border-radius: 5px;
  max-width: 50vw;
  user-select: none;
}
.select-pannel .select-option {
  font-size: 12px;
  color: #666666;
  height: 26px;
  line-height: 26px;
  min-width: 4rem;
  text-align: center;
  padding: 0 12px;
  margin: 10px 0;
  white-space: nowrap;
  word-break: keep-all;
  text-overflow: ellipsis;
  overflow: hidden;
  cursor: pointer;
}
.select-pannel .select-option:hover {
  background: rgba(96, 204, 220, 0.2);
  color: #fcb507;
  border-radius: 5px;
}
.select-pannel.marked .select-option:hover {
  color: #60ccdc;
}
.select-pannel.break .select-option:hover {
  background: rgba(115, 146, 255, 0.2);
  color: #7392ff;
}
.words-tools .tool-common .tool-item .pick-img-container {
    width: 30px;
    height: 30px;
    padding: 2px;
}
.words-tools .tool-common .tool-item .pick-img-container .pick-img {
    width: 26px;
    height: 26px;
    border-radius: 50%;
}
.words-tools .tool-common .tool-item span {
    overflow: hidden;
    width: 100%;
    white-space: nowrap;
    text-overflow: ellipsis;
    text-align: center;
}
.words-tools .tool-player {
    width: 160px;
    height: 46px;
    padding: 0 20px;
}
.words-tools .tool-player .play-btn {
    width: 120px;
    height: 46px;
    border-radius: 50px;
    background: #ffffff;
    border: 1px solid #e6e6e6;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 16px;
    cursor: pointer;
    padding: 0;
    line-height: inherit;
    color: inherit;
    margin: 0;
    text-transform: none;
}
.words-tools .tool-player .play-btn img {
    width: 24px;
    height: 24px;
    margin-right: 8px;
    max-width: 100%;
    display: block;
    vertical-align: middle;
}
</style>
